package com.ruoyi.supply.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.client.UnBuyException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
import com.ruoyi.supply.domain.TMemberConsumeLog;
import com.ruoyi.supply.domain.TMemberLog;
import com.ruoyi.supply.domain.base.BaseInfoEntity;
import com.ruoyi.supply.enums.*;
import com.ruoyi.supply.mapper.TMemberConsumeLogMapper;
import com.ruoyi.supply.mapper.TMemberLogMapper;
import com.ruoyi.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.ruoyi.supply.config.Constant.DF_PRICE;

/**
 * @author huangxiong
 * @date 2025/06/15 11:27
 */
@Slf4j
public abstract class BaseInfoService<E extends BaseInfoEntity, M extends BaseMapper<E>>  extends ServiceImpl<M, E>  {


    @Autowired
    private TInfoImgService tInfoImgService;
    @Autowired
    private TAdminAuditLogService adminAuditLogService;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private TMemberConsumeLogMapper tMemberConsumeLogMapper;
    @Autowired
    private TMemberLogMapper tMemberLogMapper;

    private final SupplyInfoTypeEnum INFO_TYPE_ENUM;

    public BaseInfoService(SupplyInfoTypeEnum infoTypeEnum) {
        this.INFO_TYPE_ENUM = infoTypeEnum;
    }




    /**
     * 查询货源 资讯
     *
     * @param id 货源 资讯主键
     * @return 货源 资讯
     */
    public E selectInfoById(Long id)
    {
        E entity = ReflectUtil.invoke(baseMapper,"selectInfoById",id);
        afterGetId(entity);

        if(isClientUser() && !Objects.equals(entity.getCreateBy(),SecurityUtils.getUserId().toString())){
            entity.setPhone(null);
            if(isLoginClientUser()){
                tMemberLogMapper.insert(TMemberLog.simpleBuild(id, MemberLogTypeEnum.CHECK+INFO_TYPE_ENUM.code));
            }
        }
        return entity;
    }



    /**
     * 查询货源 资讯列表
     * @return 货源 资讯
     */
    public List<E> selectInfoList(E search)
    {
        List<E> infoList = ReflectUtil.invoke(baseMapper,"selectInfoList",search);
        fillList(infoList);
        if(isClientUser()){
            infoList.forEach(it->{
                it.setPhone(null);
            });
        }
        afterSelectList(infoList);
        return infoList;
    }




    /**
     * 新增货源 资讯
     *
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    public int insertInfo(E bo)
    {
        try{
            String configPrice = configService.selectConfigByKey("supply.info.price");
            bo.setPrice(new BigDecimal(configPrice));
        }catch (Exception e){
            log.error("未配置或错误配置 supply.info.price {}",e.getMessage(),e);
            bo.setPrice(DF_PRICE);
        }
        bo.setCreateTime(DateUtils.getNowDate());
        if(StrUtil.isBlank(bo.getStatus())){
            bo.setStatus(SupplyInfoStatusEnum.WAIT_AUDIT.getCode());
        }
        int rows = baseMapper.insert(bo);
        tInfoImgService.batchAddByFkSupplyInfoId(bo.getId(), bo.getImgList(),bo.getMiniImgList(), INFO_TYPE_ENUM);
        return rows;
    }

    /**
     * 修改货源 资讯
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    public int updateInfo(E info)
    {
        checkPerm(info.getId());
        info.setUpdateTime(DateUtils.getNowDate());
        tInfoImgService.deleteByFkSupplyInfoId(info.getId());
        tInfoImgService.batchAddByFkSupplyInfoId(info.getId(), info.getImgList(),info.getMiniImgList(), SupplyInfoTypeEnum.LOCATION);
        return baseMapper.updateById(info);
    }

    /**
     * 批量删除货源 资讯
     *
     * @param ids 需要删除的货源 资讯主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    public int deleteInfoByIds(Long[] ids)
    {
        Arrays.stream(ids).forEach(this::checkPerm);
        tInfoImgService.deleteByFkSupplyInfoIds(ids);
        return baseMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除货源 资讯信息
     *
     * @param id 货源 资讯主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    public int deleteInfoById(Long id)
    {
        checkPerm(id);
        tInfoImgService.deleteByFkSupplyInfoId(id);
        return baseMapper.deleteById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    public void statusChange(Long id, String status) {
        SupplyInfoStatusEnum statusEnum = SupplyInfoStatusEnum.getByCode(status);
        Assert.notNull(statusEnum,  "状态值为空！");
        E info = getById(id);
        Assert.notNull(info,  "数据异常，请刷新后重试！");
        statusEnum.checkLastStatus(info.getStatus());
        info.setStatus(statusEnum.getCode());
        this.updateById(info);
        adminAuditLogService.insertLog(AdminAuditLogTableEnum.LOCATION_INFO,statusEnum,id);
    }

    public String clintGetContact(Long id) {
        if(!isBuy(id)){
            throw new UnBuyException();
        }
        QueryWrapper<E> q = new QueryWrapper<>();
        q.select("phone")
                .eq("id", id)
                .eq("status", SupplyInfoStatusEnum.AUDIT_PASS.getCode())
                .last("limit 1");
        E e = baseMapper.selectOne(q);

        return Objects.isNull(e)?null:e.getPhone();
    }



    public boolean isBuy(Long id){

        if(isCreator(id) || SecurityUtils.getLoginUser().isPaidMember()){
            return true;
        }
        TMemberConsumeLog tMemberConsumeLog = tMemberConsumeLogMapper.selectOne(
                new QueryWrapper<TMemberConsumeLog>()
                        .lambda()
                        .eq(TMemberConsumeLog::getFkMemberId, SecurityUtils.getUserId())
                        .eq(TMemberConsumeLog::getFkTableId, id)
                        .eq(TMemberConsumeLog::getFkTableType, INFO_TYPE_ENUM.code)
                        .eq(TMemberConsumeLog::getStatus, PayStatusEnum.SUCCESS.getCode())
                        .last("limit 1")
        );
        return Objects.nonNull(tMemberConsumeLog);
    }

    private boolean isCreator(Long infoId){
        QueryWrapper<E> q = new QueryWrapper<>();
        q.select("id").eq("create_by",SecurityUtils.getUserId()).eq("id",infoId);
        Long count = baseMapper.selectCount(q);
        if(count != null && count > 0){
            return true;
        }
        return false;
    }
    private void checkPerm(Long id){
        if(isClientUser()){
            Assert.equals(getById(id).getCreateBy(), SecurityUtils.getUserId(),"权限不足");
        }
    }

    private boolean isClientUser(){
        HttpServletRequest request = ServletUtils.getRequest();
        return JwtAuthenticationTokenFilter.isClient(request);
    }

    private boolean isLoginClientUser(){
        try{
            return SecurityUtils.getLoginUser().getIsClient();
        }catch (Exception e){
            return false;
        }
    }


    protected   void afterGetId(E  entity){
//        entity.setImgList(tInfoImgService.findImgByType(entity.getId(), INFO_TYPE_ENUM.getCode()));
    }
    protected void afterSelectList(List<E> list){}

    private void fillList(List<E> infoList) {
        if(CollUtil.isEmpty(infoList)){
            return;
        }
        infoList.forEach(it->{
            List<String> imgByType = tInfoImgService.findMiniImgByType(it.getId(), INFO_TYPE_ENUM.getCode());
            if(CollUtil.isEmpty(imgByType)){
                return;
            }
            // 响应缩略图
            it.setImgList(
                    imgByType
//                    imgByType
//                            .stream()
//                            .map(FileUploadUtils::getCompFileName)
//                            .collect(Collectors.toList())
            );
        });
    }
}
